package com.googlecode.maratische.google;

import static com.googlecode.maratische.google.MainController.getMainController;

import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.html.HTMLDocument;

import org.apache.log4j.Logger;

import com.googlecode.maratische.google.gui.CurrentFocusComponent;
import com.googlecode.maratische.google.gui.LinkLabel;
import com.googlecode.maratische.google.gui.PopupListenerDisplayPane;
import com.googlecode.maratische.google.listeners.DisplayPaneListener;
import com.googlecode.maratische.google.model.Feed;
import com.googlecode.maratische.google.model.Item;
import com.googlecode.maratische.google.model.Label;
import com.googlecode.maratische.google.utils.DesktopUtil;
import com.googlecode.maratische.google.utils.StringUtils;

public class DisplayPane extends JPanel implements DisplayPaneListener, CurrentFocusComponent {
	
	static Logger logger = Logger.getLogger(DisplayPane.class.getName());
	
	private JTextPane textPane;
	private JScrollPane jScrollPane;
	private LinkLabel displayLabel = new LinkLabel();
	private JTextArea commentArea = new JTextArea();

	public DisplayPane(PopupListenerDisplayPane popupListener) {
		super();
		this.setLayout(new BorderLayout());
		
		initLabel();
		displayLabel.addMouseListener(new MouseAdapter() {
			/**
			 * запускается только когда пользователь кликает по конкретно title окна, и открывается странчика в новом окне
			 */
			@Override
			public void mouseClicked(MouseEvent e) {
				MainController controller = getMainController();
				controller.markItemAsRead(controller.getSelectedItem());
			}
		});
		initScrollPane(popupListener);
		
		add(commentArea,BorderLayout.SOUTH);
		commentArea.setVisible(false);
		
		this.addFocusListener(new FocusAdapter() {
			@Override
			public void focusGained(FocusEvent e) {
				super.focusGained(e);
				SwingUtilities.invokeLater(new Runnable() { public void run() { jScrollPane.requestFocus(); } } );
			}
		});
	}

	private void initLabel() {
		this.add(displayLabel, BorderLayout.NORTH);
		
	}
	private void initScrollPane(PopupListenerDisplayPane popupListener) {
		jScrollPane = new JScrollPane();
		jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		
		textPane = new JTextPane();
		jScrollPane.setViewportView(textPane);
		textPane.setLayout(new BorderLayout());

		HTMLDocument document = new HTMLDocument();
		textPane.setStyledDocument(document);
        textPane.setEditable(false);
//        textPane.setFocusable(false);
        jScrollPane.setFocusable(true);
        
		textPane.addHyperlinkListener(new HyperlinkListener() {
			public void hyperlinkUpdate(HyperlinkEvent event) {
				if (event.getEventType() == HyperlinkEvent.EventType.ENTERED) {
					textPane.setToolTipText(event.getURL().toString());
				}
				if (event.getEventType() == HyperlinkEvent.EventType.EXITED) {
					textPane.setToolTipText(null);
				}
				if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
					try {
						DesktopUtil.openUrlInBrowser(event.getURL().toURI());
					} catch (IOException e1) {
						e1.printStackTrace();
					} catch (URISyntaxException e1) {
						e1.printStackTrace();
					}
			    }
			}
		});
		textPane.addFocusListener(new FocusAdapter() {
			@Override
			public void focusGained(FocusEvent e) {
				super.focusGained(e);
				SwingUtilities.invokeLater(new Runnable() { public void run() { jScrollPane.requestFocus(); } } );
			}
		});
		
		textPane.addMouseListener(popupListener);
		this.add(jScrollPane, BorderLayout.CENTER);
	}

	/**
	 * возвращает сам JList компонент, необходим для передачи фокуса
	 * @return
	 */
	public JComponent getCurrentFocusComponent() {
		return this.jScrollPane;
	}
	
	public synchronized void setDisplayedItem(Item item) throws Exception {
		if (item != null) {
			commentArea.setVisible(false);
			if (item.getLabelId() != null) {
				Label label = DaoAction.getDaoAction().getLabelDao().get(item.getLabelId());
				if (label.getComment() != null && label.getComment().length()>0) {
					commentArea.setVisible(true);
					commentArea.setText(label.getComment());
				}
			}
			Feed feed = DaoAction.getDaoAction().getFeedDao().get(item.getFeedId() != null ? item.getFeedId() : getMainController().getSelectedFeed().getId());
			displayLabel.setText(StringUtils.removeXml(item.getTitle()));
			displayLabel.setFontSize(getMainController().getDisplayPaneFontSize());
			displayLabel.setUrl(item.getLink());
//			setText(item.getDescription());
			StringBuilder result = new StringBuilder();
			result.append("<span style=\"font-size: "+getMainController().getDisplayPaneFontSize()+"\">");
			if (feed.getName() != null && feed.getName().length()>0) {
				result.append("<span style=\"color:gray\">from: ").append(feed.getName()).append("</span>");
			}
			if (item.getAuthor() != null && item.getAuthor().length()>0 && !"(author unknown)".equals(item.getAuthor())) {
				result.append("<span style=\"color:gray\">&nbsp;&nbsp;&nbsp;&nbsp;by: ").append(item.getAuthor()).append("</span><br/>");
			}
			result.append("<br/>");
			/**
			 * FIXME пробуем решить проблему 66
			 */
			StringBuilder description2 = new StringBuilder();
			String description = item.getDescription();
			if (description != null) {
				String temp = null;
				Pattern p1 = Pattern.compile(".*[ ](width)[ =].*");
				Pattern p2 = Pattern.compile(".*[ ]height[ =].*");
				while ( (temp = StringUtils.getBetweenString(description, "<img ", ">")) != null) {
					temp = "<img "+temp+">";
					description2.append(StringUtils.getBeforeString(description, "<img "));
					description = StringUtils.getAfterString(description, "<img ", ">");
					int i =  0;
					boolean b1 = false;
					boolean b2 = false;
					if ( b1 = p1.matcher(temp).matches()) {
						i++;
					}
					if (b2 = p2.matcher(temp).matches()) {
						i++;
					}
					if (i==1) {
						//проблема!
						if (b1) {
							logger.debug("remove width from "+temp);
							temp = temp.replaceFirst(" width", " _width");
						}
						if (b2) {
							logger.debug("remove height from "+temp);
							temp = temp.replaceFirst(" height", " _height");
						}
					}
					description2.append(temp);
				}
				description2.append(description);
			}
			result.append(description2.toString());
			result.append("</span>");
			setText(result.toString());
		} else {
			displayLabel.setText("");
			displayLabel.setUrl(null);
			setText("");
		}
	}
	
	@Override
	public void addKeyListener(KeyListener l) {
		jScrollPane.addKeyListener(l);
		textPane.addKeyListener(l);
	}
	String originDescription = "";
	public void setText(String description) throws Exception {
		if (description == null) {
			description = "";
		}
		this.originDescription = description;
		while (description.indexOf("</embed>")>-1) {
			String temp = "<embed"+StringUtils.getBetweenString(description, "<embed", "</embed>")+"</embed>";
			description = StringUtils.replace(description, temp, "VIDEO_TAG");
		}
		while (description.indexOf("</iframe>")>-1) {
			String temp = "<iframe"+StringUtils.getBetweenString(description, "<iframe", "</iframe>")+"</iframe>";
			description = StringUtils.replace(description, temp, "IFRAME_TAG");
		}
//        logger.debug(description);
       	textPane.setContentType( "text/html" );
		try {
			textPane.setText(description);
		} catch (Exception e ) {
			textPane.setText("");
			throw new Exception(e.getMessage());
		}
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				DisplayPane.this.jScrollPane.getViewport().setViewPosition(new Point(0, 0));
			}
		});
	}

		
	private static final long serialVersionUID = -6046597064014713215L;

}
